#include "ScrollPane.h"
#include "../std.h"
#include <MAUtil/Graphics.h>

ScrollPane::ScrollPane(int x, int y, int width, int height, Widget* parent, int rows, int cols)
			   : Layout(x, y, width, height, parent, rows, cols)
{}

ScrollPane::~ScrollPane()
{}

void ScrollPane::runTimerEvent()
{
	if(kineticTimer)
	{
			velocity = Point((int)(velocity.x * .99), (int)(velocity.y * .99));

			float x = velocity.x;
			if(x < 0) x *=-1;

			float y = velocity.y;
			if(y < 0) y *=-1;

			if (x < .1) velocity.x = 0;
			if (y < .1) velocity.y = 0;

			if (!velocity.x && !velocity.y)
			{
					stop();
			}

			yOffset += ((int)velocity.y << 16);

			if(yOffset > 0) {
					stop();
					yOffset = 0;
			}
			if(getChildren().size() > 0)
			{
				Widget *c = children[getChildren().size()-1];
				if(((yOffset>>16)*-1) > c->getPosition().y+c->getHeight()-getHeight()) {
						stop();
						if(listFrontOutsideBounds())
							yOffset = ((c->getPosition().y+c->getHeight()-getHeight()) << 16)*-1;
						else
							yOffset = 0;
						//LOG("1. Set yOffset to %d", yOffset>>16);
				}
			}
	}
	else
	{
		yOffset = (yOffsetFrom<<16) + (yOffsetTo-yOffsetFrom)*(((maGetMilliSecondCount()-animTimeStart)<<16)/DURATION);
		if(yOffsetInc<0 && yOffset<=yOffsetTo<<16) {
				yOffset = yOffsetTo<<16;
				//LOG("2. Set yOffset to %d", yOffset>>16);
				Environment::getEnvironment().removeTimer(this);
		}
		else if(yOffsetInc>0 && yOffset>=yOffsetTo<<16) {
				yOffset = yOffsetTo<<16;
				//LOG("3. Set yOffset to %d", yOffset>>16);
				Environment::getEnvironment().removeTimer(this);
		}
	}

    requestRepaint();
}

/*void ScrollPane::pointerMoveEvent(MAPoint2d point)
{
	if(this->contains(point.x, point.y))
	{
		if(previousPoints.size() > 0)
		{
			Point currPoint(0, point.y);
			float currTime = maGetMilliSecondCount();

			Point previousPoint(previousPoints[previousPoints.size()-1]);
			float previousTime(previousTimes[previousTimes.size()-1]);
			Point diff(currPoint.x-previousPoint.x, currPoint.y-previousPoint.y);

			previousPoints.add(currPoint);
			previousTimes.add(currTime);
			if (previousPoints.size() >= HISTORY_LENGTH) {
					previousPoints.remove(0);
					previousTimes.remove(0);
			}

			yOffset += (int)diff.y << 16;

			requestRepaint();
		}
		else
		{
			previousPoints.add(Point(0, point.y));
			previousTimes.add(maGetMilliSecondCount());
		}
	}
	LOG("1. Pointer Mouse Event: x[%d] - y[%d]", point.x, point.y);
}

void ScrollPane::pointerReleaseEvent(MAPoint2d point)
{
	LOG("SCROLLPANE pointer release");
	int y = point.y-(yOffset>>16);

	Point currPoint(0, point.y);
	float currTime = maGetMilliSecondCount();
	Point firstPoint = previousPoints[0];
	float firstTime = previousTimes[0];
	Point diff( currPoint.x-firstPoint.x, currPoint.y-firstPoint.y );
	float time = (currTime - firstTime) / (1000 / 24);
	if(time > 0)
	{
		velocity = Point((int)(diff.x / time), (int)(diff.y / time));
		kineticTimer = true;
		Environment::getEnvironment().addTimer(this, MS_PER_FRAME, FRAMES+1);
		requestRepaint();
	}
	LOG("1. Pointer Mouse Release: x[%d] - y[%d]", point.x, point.y);
}

void ScrollPane::pointerPressEvent(MAPoint2d point)
{
	if(this->contains(point.x, point.y))
	{
		stop();
		previousPoints.add(Point(0, point.y));
		previousTimes.add(maGetMilliSecondCount());

		requestRepaint();
	}
	LOG("1. Pointer Press Event: x[%d] - y[%d]", point.x, point.y);
}*/

void ScrollPane::stop()
{
		kineticTimer = false;
		previousPoints.clear();
		previousTimes.clear();
		Environment::getEnvironment().removeTimer(this);
}

void ScrollPane::scrollDown(int pixels)
{
	velocity = Point(0, pixels);
	kineticTimer = true;
	Environment::getEnvironment().addTimer(this, MS_PER_FRAME, FRAMES+1);
	requestRepaint();
}

void ScrollPane::scrollUp(int pixels)
{
	velocity = Point(0, pixels * -1);
	kineticTimer = true;
	Environment::getEnvironment().addTimer(this, MS_PER_FRAME, FRAMES+1);
	requestRepaint();
}

bool ScrollPane::listFrontOutsideBounds()
{
	bool outside = false;
	for(int i = 0; i < children.size(); i++)
	{
		int y = (children[i]->getPosition().y + (yOffset>>16));
		if(y < 0) outside = true;
	}
	return outside;
}

bool ScrollPane::listBackOutsideBounds()
{
	bool outside = false;
	for(int i = 0; i < children.size(); i++)
	{
		int y = (children[i]->getPosition().y + children[i]->getHeight() + (yOffset>>16));
		if(y > paddedBounds.height) outside = true;
	}
	return outside;
}

void ScrollPane::draw(bool forceDraw)
{
	int i = 0;

	Gfx_pushMatrix();
	Gfx_translate(relX, relY);

	BOOL res = Gfx_intersectClipRect(0, 0, bounds.width, bounds.height);

	if(res) {
			if((isDirty() || forceDraw) && shouldDrawBackground) {
					drawBackground();
			}

			Gfx_translate(paddingLeft, paddingTop);
			res = Gfx_intersectClipRect(0, 0, paddedBounds.width, paddedBounds.height);

			Gfx_translate(0, (yOffset>>16));

			if(res)
			{
					for(i = 0; i < children.size(); i++)
					{
							children[i]->draw();
					}
			}

			Gfx_popClipRect();
	}
	setDirty(false);

	Gfx_popMatrix();
	Gfx_popClipRect();
}

//The Layout may be inside another selection mechanism
void ScrollPane::setSelected(bool e)
{
	Environment& env = Environment::getEnvironment();
	if(!listening && e) {
		//LOG("KLB at %8x is now listening to the pointer", this);
		//env.addPointerListener(this);
		listening = true;
	}
	else if(listening && !e) {
		//env.removePointerListener(this);
		//LOG("KLB at %8x is now NOT listening to the pointer", this);
		listening = false;
	}

	Layout::setSelected(e);
}

void ScrollPane::setEnabled(bool e)
{
	Environment& env = Environment::getEnvironment();
	if(!listening && e) {
		//LOG("KLB at %8x is now listening to the pointer", this);
		//env.addPointerListener(this);
		listening = true;
	}
	else if(listening && !e) {
		//LOG("KLB at %8x is now NOT listening to the pointer", this);
		//env.removePointerListener(this);
		listening = false;
	}

	Layout::setEnabled(e);
}

void ScrollPane::reset()
{
	yOffset = 0;
}
